/**
  * Author: Mei
  * Date: 2020-12-30 19:13
  * Description: 反转tuple
  *
  */
#include "../head.h"

template<int ... a>
struct IndexTuple {
};

template<int I, typename IndexTuple, typename ...Types>
struct make_indexes_indexes_impl;

//把参数进行拆分为1+n  直到最后两个为空  调用下面的特化
template<int I, int ... Indexes, typename T, typename ...Types>
struct make_indexes_indexes_impl<I, IndexTuple<Indexes...>, T, Types...> {
    using type =typename make_indexes_indexes_impl<I - 1,
            IndexTuple<Indexes..., I - 1>,
            Types...>::type;
};
template<int I, int ... Indexes>
struct make_indexes_indexes_impl<I, IndexTuple<Indexes...>> {
    using type = IndexTuple<Indexes...>;
};

//逆序生成索引  根据推导出的Types即可得到索引的数量
template<typename ...Types>
struct make_reverse_indexes : make_indexes_indexes_impl<sizeof...(Types), IndexTuple<>, Types...> {
};

//反转 返回tuple
template<class ... Args, int ... Indexes>
//反推出Indexes的值
auto
reverse_imp(tuple<Args...> &&tup, IndexTuple<Indexes...> &&) ->
decltype(make_tuple(get<Indexes>(forward<tuple<Args...>>(tup))...)) {
    //需要返回最终生成的tuple
    return make_tuple(get<Indexes>(forward<tuple<Args...>>(tup))...);
}

template<class ...Args>
auto
Reverse(tuple<Args...> &&tup) -> decltype(reverse_imp(
        forward<tuple<Args...>>(tup),
        typename make_reverse_indexes<Args...>::type()
)) {
    return reverse_imp(
            forward<tuple<Args...>>(tup), //传入tuple
            typename make_reverse_indexes<Args...>::type() //生成IndexTuple  模板参数为逆序索引
    );
}

//打印
template<typename Tuple, size_t N>
struct TuplerPrinter {
    static void print(const Tuple &t) {
        TuplerPrinter<Tuple, N - 1>::print(t);
        cout << ", " << get<N - 1>(t);
    }
};

template<typename Tuple>
struct TuplerPrinter<Tuple, 1> {
    static void print(const Tuple &tup) {
        cout << get<0>(tup);
    }
};

template<typename ...Args>
void PrintTuple(const tuple<Args...> &tup) {
    cout << "(";
    TuplerPrinter<decltype(tup), sizeof...(Args)>::print(tup);
    cout << ")" << endl;
}

//测试tuple中的get函数  传入可变模板参数
template<typename T>
void print1(T a) {
    cout << a << endl;
}

template<typename T, typename ...Args>
void print1(T b, Args &&... c) {
    cout << b << " ";
    print1(c...);
}

template<int...>
struct IndexTp {
};

//template<typename ...Args, int ... Indexes>
template<typename ...Args, typename ... Indexes>
auto
tuple_get_test(tuple<Args...> &tp, Indexes... indexes)
-> decltype(make_tuple(get<indexes>(tp)...))
{
    //cout << "args: " << sizeof...(Args) << endl;
    //cout << "indexes: " << sizeof...(indexes) << endl;
    //print1(indexes...);
    return make_tuple(get<indexes>(tp)...);
}

template<class ... Args, int ... Indexes>
//反推出Indexes的值
auto
reverse_imp1(tuple<Args...> &&tup, IndexTuple<Indexes...> &&) ->
decltype(make_tuple(get<Indexes>(forward<tuple<Args...>>(tup))...)) {
    print1(Indexes...);
    //需要返回最终生成的tuple
    return make_tuple(get<Indexes>(forward<tuple<Args...>>(tup))...);
}

template<class ...Args>
auto
Reverse1(tuple<Args...> &&tup) -> decltype(reverse_imp(
        forward<tuple<Args...>>(tup),
        typename make_reverse_indexes<Args...>::type()
)) {
    return reverse_imp1(
            forward<tuple<Args...>>(tup), //传入tuple
            typename make_reverse_indexes<Args...>::type() //生成IndexTuple  模板参数为逆序索引
    );
}

int main() {
    auto tp1 = make_tuple(1, 2, 3, 'a', 10, 29);
    //auto tp2 = Reverse1(make_tuple(1, 2, 3, 'a', 10, 29));
    //PrintTuple(tp1);
    //PrintTuple(tp2);

    IndexTp<0, 1, 2, 3, 4, 5> ip;
    //auto tp3 = tuple_get_test(tp1, ip);
    auto tp3 = tuple_get_test(tp1, 0, 1, 2, 3, 4, 5);
    PrintTuple(tp3);

    return 0;
}